package demoMod.stsconsole.interfaces;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.stream.MalformedJsonException;
import demoMod.stsconsole.helpers.DataTypeAdapter;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public interface CustomSavable<T> {
    Gson saveFileGson = new GsonBuilder()
            .registerTypeAdapterFactory(DataTypeAdapter.FACTORY)
            .setObjectToNumberStrategy(in -> {
                String value = in.nextString();
                try {
                    long test = Long.parseLong(value);
                    if (test <= Integer.MAX_VALUE) {
                        return Integer.parseInt(value);
                    } else {
                        return test;
                    }
                } catch (NumberFormatException var6) {
                    try {
                        Float f = Float.valueOf(value);
                        if ((f.isInfinite() || f.isNaN()) && !in.isLenient()) {
                            throw new MalformedJsonException("JSON forbids NaN and infinities: " + f + "; at path " + in.getPath());
                        } else {
                            return f;
                        }
                    } catch (NumberFormatException var5) {
                        throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPath(), var5);
                    }
                }
            })
            .setPrettyPrinting()
            .create();

    T onSave();

    void onLoad(T object);

    default Type savedType() {
        Class<?> clz = getClass();
        for (Type t : clz.getGenericInterfaces()) {
            if (t instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) t;
                if (pt.getRawType().equals(CustomSavable.class)) {
                    return pt.getActualTypeArguments()[0];
                }
            }
        }

        throw new RuntimeException("Implement [Type savedType()]");
    }

    default JsonElement onSaveRaw() {
        return saveFileGson.toJsonTree(onSave());
    }


    default void onLoadRaw(JsonElement value) {
        if (value != null) {
            T parsed = saveFileGson.fromJson(value, savedType());
            onLoad(parsed);
        } else {
            onLoad(null);
        }
    }
}
